//package java_cup;

//import java.util.Dictionary;

/**
 * This class represents a terminal SymbolDraft in the grammar. Each terminal has a
 * textual name, an index, and a string which indicates the type of object it
 * will be implemented with at runtime (i.e. the class of object that will be
 * returned by the scanner and pushed on the parse stack to represent it).
 *
 * @version last updated: 7/3/96
 * @author Frank Flannery
 */
public class Vt : SymbolDraft {

    /*-----------------------------------------------------------*/
    /*--- Constructor(s) ----------------------------------------*/
    /*-----------------------------------------------------------*/

    /**
     * Full constructor.
     * 
     * @param name the name of the terminal.
     * @param type the type of the terminal.
     */
    public Vt(String name, String type, int precedenceSide,
        int precedenceNum)
        /* superclass does most of the work */
        : base(name, type) {

        /* TryAdd to set of AllVns terminals and check for duplicates */
        //Object conflict = _itemSet2State.Add(name, this);
        //if (conflict != null)
        //    // can't throw an execption here because this is used in static
        //    // initializers, so we do a crash instead
        //    // was:
        //    // throw new internal_error("Duplicate terminal (" + name + ") created");
        //    (new internal_error("Duplicate terminal (" + name + ") created")).crash();
        if (!_name2Terminal.TryAdd(name, this)) {
            // can't throw an execption here because this is used in static
            // initializers, so we do a crash instead
            // was:
            // throw new internal_error("Duplicate terminal (" + name + ") created");
            (new InternalError("Duplicate terminal (" + name + ") created")).crash();
        }

        /* assign a unique index */
        _index = next_index++;

        /* set the precedence */
        _precedenceNum = precedenceNum;
        _precedenceSide = precedenceSide;

        /* TryAdd to by_index set */
        _index2Terminal.Add(_index, this);
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /**
     * Constructor for non-precedented terminal
     */

    public Vt(String name, String type)
        : this(name, type, Associativity.noPrec, -1) {
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /**
     * Constructor with default type.
     * 
     * @param name the name of the terminal.
     */
    public Vt(String name)
        : this(name, null) {
    }

    /*-----------------------------------------------------------*/
    /*-------------------  Class Variables  ---------------------*/
    /*-----------------------------------------------------------*/

    public int _precedenceNum;
    public int _precedenceSide;

    /*-----------------------------------------------------------*/
    /*--- (Access to) Static (Class) Variables ------------------*/
    /*-----------------------------------------------------------*/

    /**
     * Table of AllVns terminals. Elements are stored using name strings as the key
     */
    public static Dictionary<String, Vt> _name2Terminal = new();

    // Hm Added clear to clear AllVns static fields
    public static void clear() {
        _name2Terminal.Clear();
        _index2Terminal.Clear();
        EOF = new Vt("EOF");
        error = new Vt("error");
    }

    /** Access to AllVns terminals. */
    public static IEnumerable<Vt> AllTerminals() {
        return _name2Terminal.Values;
    }

    /** Lookup a terminal by name string. */
    public static Vt Find(String withName) {
        if (withName == null)
            return null;
        else
            return _name2Terminal[withName];
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Table of AllVns terminals indexed by their index Count. */
    public static Dictionary<int, Vt> _index2Terminal = new();

    /** Lookup a terminal by index. */
    public static Vt Find(int indx) {
        return _index2Terminal[indx];
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Total Count of terminals. */
    public static int Count => _name2Terminal.Count;

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Static counter to assign unique index. */
    public static int next_index;

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Special terminal for end of input. */
    public static Vt EOF = new Vt("EOF");

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** special terminal used for error recovery */
    public static Vt error = new Vt("error");

    /*-----------------------------------------------------------*/
    /*--- General Methods ---------------------------------------*/
    /*-----------------------------------------------------------*/

    /** Report this SymbolDraft as not being a non-terminal. */
    /*@Override*/
    public override bool IsVn => false;

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** Convert to a string. */
    /*@Override*/
    public override string ToString() {
        return base.ToString() + "[" + Index + "]";
    }

    /* . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . */

    /** get the precedence of a terminal */
    public int PrecedenceNum => _precedenceNum;

    public int PrecedenceSide => _precedenceSide;

    /** set the precedence of a terminal */
    public void setPrecedence(int p, int newPrec) {
        _precedenceSide = p;
        _precedenceNum = newPrec;
    }

    /*-----------------------------------------------------------*/

}
